﻿using MaterialDesignThemes.Wpf;
using Microsoft.Extensions.Configuration;
using Minotaur.App.Core;
using Minotaur.App.Domains.Dto;
using Minotaur.App.Domains.Model.Account;
using Minotaur.App.Domains.Model.Menu;
using Minotaur.App.Domains.Model.Organization;
using Minotaur.App.Domains.Model.Personal;
using Minotaur.App.Domains.Model.Position;
using Minotaur.App.Domains.Model.Role;
using Minotaur.App.Domains.Tenement;
using Minotaur.App.Views;
using Newtonsoft.Json;
using Prism.Commands;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Regions;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;

namespace Minotaur.App.ViewModels
{
    public class LogInViewModel : BindableBase
    {
        private string _title = "Prism Application";
        private SqlSugarScope sqlSugarScope;
        private readonly IConfiguration configuration;
        private readonly IContainerExtension _container;
        private readonly IRegionManager _regionManager;
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        private string _Account;

        /// <summary>
        /// 账号
        /// </summary>
        public string Account
        {
            get { return _Account; }
            set { SetProperty(ref _Account, value); }
        }
        private string _Code;

        /// <summary>
        /// 是否系统管理员
        /// </summary>
        private bool IsAdmin { get => Account == "admin"; }

        private string _ErrorMessage;

        /// <summary>
        /// 错误提示
        /// </summary>
        public string ErrorMessage { get => _ErrorMessage; set { SetProperty(ref _ErrorMessage, value); } }

        private Visibility _ErrorMessageVisibility = Visibility.Collapsed;

        /// <summary>
        /// 错误提示-是否显示
        /// </summary>
        public Visibility ErrorMessageVisibility { get => _ErrorMessageVisibility; set { SetProperty(ref _ErrorMessageVisibility, value); } }

        private Visibility _LoadingVisibility = Visibility.Visible;
        /// <summary>
        /// 是否是第一次
        /// </summary>
        private bool _isFrist;

        /// <summary>
        /// 错误提示-是否显示
        /// </summary>
        public Visibility LoadingVisibility { get => _LoadingVisibility; set { SetProperty(ref _LoadingVisibility, value); } }

        /// <summary>
        /// 租户编码
        /// </summary>
        public string Code
        {
            get { return _Code; }
            set { SetProperty(ref _Code, value); }
        }

        private string _PassWord;
        /// <summary>
        /// 用户密码
        /// </summary>
        public string PassWord
        {
            get { return _PassWord; }
            set
            {

                if (string.IsNullOrEmpty(value) && IsFrist)
                {
                    IsFrist = true;
                    IsValid = true;
                    throw new ArgumentException("密码不能为空！");
                }
                else
                {
                    IsFrist = true;
                    IsValid = false;
                }
                SetProperty(ref _PassWord, value);
            }
        }
        private bool _DialogHostOpend;
        /// <summary>
        /// 租户
        /// </summary>
        public bool DialogHostOpend
        {
            get => _DialogHostOpend;
            set { SetProperty(ref _DialogHostOpend, value); }
        }


        private bool _IsValid;
        /// <summary>
        /// 租户
        /// </summary>
        public bool IsValid
        {
            get => _IsValid;
            set { SetProperty(ref _IsValid, value); }
        }
        /// <summary>
        /// 页面线程
        /// </summary>
        private Dispatcher _Dispatcher;

        public Dispatcher Dispatcher { get { return _Dispatcher; } set { SetProperty(ref _Dispatcher, value); } }

        /// <summary>
        /// 当前窗口
        /// </summary>
        private Window _currentWindow;

        public LogInViewModel(SqlSugarScope sqlSugarScope, IConfiguration configuration, IContainerExtension _container,
        IRegionManager _regionManager)
        {
            this.sqlSugarScope = sqlSugarScope;
            this.configuration = configuration;
            this._container = _container;
            this._regionManager = _regionManager;
        }

        public Window CurrentWindow { get { return _currentWindow; } set { SetProperty(ref _currentWindow, value); } }

        /// <summary>
        /// 关闭事件
        /// </summary>
        public ICommand CloseComand => new DelegateCommand(CloseAction);

        public ICommand LogInCommand => new DelegateCommand(LogInAction);

        public ICommand CloseDialogCommand => new DelegateCommand(CloseDialogAction);

        public bool IsFrist { get => _isFrist; set => SetProperty(ref _isFrist, value); }

        private void CloseDialogAction()
        {
            this.DialogHostOpend = false;
            this.ErrorMessageVisibility = Visibility.Collapsed;
        }

        private void LogInAction()
        {
            this.DialogHostOpend = false;
            if (!string.IsNullOrEmpty(this.Account) && !IsValid && !string.IsNullOrEmpty(this.Code))
            {
                this.LoadingVisibility = Visibility.Visible;
                this.DialogHostOpend = true;
                Task.Run(async () =>
                {
                    IDbContext dBContext = new DBContext(this.sqlSugarScope);
                    AppDataContext.dbContext=dBContext;
                    //查找租户信息
                    var tenEntity = await dBContext.MasterDb.Queryable<TenantInformation>().
                    Where(o => o.Code == this.Code).FirstAsync();
                    if (tenEntity is null)
                    {
                        this.GenerateErrorMessage("未找到租户信息,请联系系统管理员!");
                        return;
                    }
                    //查找数据库信息
                    ISqlSugarClient sqlSugarClient = dBContext.GetDB(this.Code, GlobalConst.GolbalBusinessDataBaseTag);
                    if (sqlSugarClient is null)
                    {
                        this.GenerateErrorMessage("未找到数据库信息,请联系系统管理员!");
                        return;
                    }
                    //查找租户信息
                    AccoutInfo accoutInfo = await dBContext.BusinessDb.Queryable<AccoutInfo>().FirstAsync(o => o.Account == this.Account);
                    if (accoutInfo is null)
                    {
                        this.GenerateErrorMessage("当前用户名不存在,请联系系统管理员！");
                        return;
                    }
                    GlobalConfigModel globalConfigModel = this.configuration.Get<GlobalConfigModel>();
                    var passd = IsAdmin ? this.PassWord : this.PassWord.AESDecrypt(globalConfigModel?.Crypto?.AES?.Key);
                    if (accoutInfo.Password != passd)
                    {
                        this.GenerateErrorMessage("当前输入密码不正确，请重新输入！");
                        return;
                    }
                    int lan = (int)((accoutInfo.Language + "").ConvertEnumEvent<Domains.Enum.LanguageType>());
                    try
                    {
                        var users = await dBContext.BusinessDb.Queryable<Employee>()
                               .LeftJoin<Position>((a, b) => b.AutoId == a.PositionId)
                               .LeftJoin<Organization>((a, b, c) => c.AutoId == a.PositionId)
                               .LeftJoin<EmployeeRes>((a, b, c, d) => d.EmpId == a.AutoId && d.Lan == lan)
                               .LeftJoin<PositionRes>((a, b, c, d, e) => a.PositionId == e.PositionId && e.Lan == lan)
                               .LeftJoin<OrganizationRes>((a, b, c, d, e, f) => a.OrgId == f.OrgId && f.Lan == lan)
                               .Where((a, b, c, d, e, f) => a.AutoId == accoutInfo.EmpId)
                               .Select((a, b, c, d, e, f) => new GlobalUserModel
                               {
                                   EmpCode = a.EmpCode,
                                   EmpId = a.AutoId,
                                   EmpName = d.Value,
                                   OrgId = f.OrgId,
                                   OrgName = f.Value,
                                   PositionId = e.PositionId,
                                   PositionName = e.Value
                               }).FirstAsync()
                              ;
                        if (users is null)
                        {
                            this.GenerateErrorMessage("当前用户名不存在,请联系系统管理员！");
                            return;
                        }
                        users.IsAdmin = accoutInfo.Account == "admin";
                        #region 获取菜单信息
                        await GenerateMenuInfo(users, dBContext.BusinessDb, lan);
                        #endregion
                        AppDataContext.GlobalUserModel = users;
                        AppDataContext.GlobalUserModel.Account = accoutInfo.Account;
                        AppDataContext.GlobalUserModel.Language = accoutInfo.Language;
                        AppDataContext.GlobalUserModel.TenementCode = tenEntity.Code;
                        AppDataContext.GlobalUserModel.TenementName = tenEntity.CNName;
                        AppDataContext.GlobalUserModel.TenementPhone = tenEntity.Phone;
                        AppDataContext.GlobalUserModel.UserId = accoutInfo.AutoId;
                        dBContext.GlobalUserModel = AppDataContext.GlobalUserModel;

                        this.Dispatcher.Invoke(() =>
                        {
                            _container.RegisterSingleton<GlobalUserModel>(() => dBContext?.GlobalUserModel);
                            _container.RegisterSingleton<IDbContext>(() => dBContext);
                            this.ErrorMessageVisibility = Visibility.Collapsed;
                            this.LoadingVisibility = Visibility.Visible;
                            this.DialogHostOpend = false;
                            var mainWindow = _container.Resolve<MainWindow>();
                            RegionManager.SetRegionManager(mainWindow, _regionManager);
                            RegionManager.UpdateRegions();
                            Application.Current.MainWindow = mainWindow;
                            Application.Current.MainWindow.Show();
                            this.CurrentWindow.Close();
                        });
                    }
                    catch (System.Exception es)
                    {
                        this.GenerateErrorMessage("系统错误！");
                    }

                });
            }
            else
            { 
                this.LoadingVisibility = Visibility.Collapsed;
                this.DialogHostOpend = false;
                HandyControl.Controls.Growl.Error("页面上有必填字段未填写!");
            }
            // throw new NotImplementedException();
        }

        /// <summary>
        /// 组装方法
        /// </summary>
        /// <param name="users"></param>
        /// <exception cref="NotImplementedException"></exception>
        private async Task GenerateMenuInfo(GlobalUserModel users, ISqlSugarClient businessDb, int lan)
        {
            List<MenuInfoDto> menuInfoDtos = new List<MenuInfoDto>();
            if (users.IsAdmin)
                menuInfoDtos = await businessDb.Queryable<MenuInfo>()
                             .LeftJoin<MenuRes>((a, b) => a.AutoId == b.MenuId && b.Lan == lan)
                             .Where((a, b) => a.Status.Value)
                             .Select((a, b) => new MenuInfoDto()
                             {
                                 Address = a.Address,
                                 Code = a.Code,
                                 Icon = a.Icon,
                                 Name = b.Value,
                                 ParentCode = a.ParentCode,
                                 Sequence = a.Sequence,
                                 Status = a.Status,
                             }).ToListAsync();
            else
                menuInfoDtos = await businessDb.Queryable<MenuInfo>().
                     InnerJoin<MenuRole>((a, b) => a.AutoId == b.MenuId)
                     .InnerJoin<RoleEmployeeInfo>((a, b, c) => b.RoleId == c.RoleId)
                     .LeftJoin<MenuRes>((a, b, c, d) => a.AutoId == d.MenuId && d.Lan == lan)
                     .Where((a, b, c, d) => c.EmpId == users.EmpId && a.Status.Value)
                     .Select((a, b, c, d) => new MenuInfoDto()
                     {
                         Address = a.Address,
                         Code = a.Code,
                         Icon = a.Icon,
                         Name = d.Value,
                         ParentCode = a.ParentCode,
                         Sequence = a.Sequence,
                         Status = a.Status,
                     }).ToListAsync();
            List<MenuInfoDto> resultMenuInfo = new List<MenuInfoDto>();
            if (menuInfoDtos.Any())
            {
                foreach (var item in menuInfoDtos.OrderBy(o => o.Sequence).Where(O => string.IsNullOrEmpty(O.ParentCode)))
                {
                    List<BussineKeyValueDto> dtos = JsonConvert.DeserializeObject<List<BussineKeyValueDto>>(item.Icon);
                    if (dtos.Any(o => o.Label == "pc"))
                    {
                        item.IconKind = (PackIconKind)int.Parse(dtos.FirstOrDefault(o => o.Label == "pc").Value ?? "0");
                    }
                    foreach (var oitem in menuInfoDtos.Where(o => o.ParentCode == item.Code))
                    {
                        dtos = JsonConvert.DeserializeObject<List<BussineKeyValueDto>>(oitem.Icon);
                        if (dtos.Any(o => o.Label == "pc"))
                        {
                            oitem.IconKind = (PackIconKind)int.Parse(dtos.FirstOrDefault(o => o.Label == "pc").Value ?? "0");
                        }
                        foreach (var tItem in menuInfoDtos.Where(o => o.ParentCode == oitem.Code))
                        {
                            dtos = JsonConvert.DeserializeObject<List<BussineKeyValueDto>>(tItem.Icon);
                            if (dtos.Any(o => o.Label == "pc"))
                            {
                                tItem.IconKind = (PackIconKind)int.Parse(dtos.FirstOrDefault(o => o.Label == "pc").Value ?? "0");
                            }
                            foreach (var fItem in menuInfoDtos.Where(o => o.ParentCode == tItem.Code))
                            {
                                dtos = JsonConvert.DeserializeObject<List<BussineKeyValueDto>>(fItem.Icon);
                                if (dtos.Any(o => o.Label == "pc"))
                                {
                                    fItem.IconKind = (PackIconKind)int.Parse(dtos.FirstOrDefault(o => o.Label == "pc").Value ?? "0");
                                }
                                fItem.ModuleCode = item.Code;
                                tItem.Childs.Add(fItem);
                            }
                            tItem.ModuleCode = item.Code;
                            oitem.Childs.Add(tItem);
                        }
                        oitem.ModuleCode = item.Code;
                        item.Childs.Add(oitem);
                    }
                    item.ModuleCode = item.Code;
                    resultMenuInfo.Add(item);
                }
                users.MenuInfos = resultMenuInfo;
            }
        }

        private void GenerateErrorMessage(string errorMessage)
        {
            this.Dispatcher.Invoke(() =>
            {
                this.ErrorMessage = errorMessage;
                this.LoadingVisibility = Visibility.Collapsed;
                this.DialogHostOpend = false;
                HandyControl.Controls.Growl.Error(errorMessage);
            });
        }
        private void CloseAction()
        {
            Application.Current.Shutdown();
        }
    }
}
